package com.tarena.lbs.content.service.impl;

import com.tarena.lbs.activity.api.ActivityApi;
import com.tarena.lbs.activity.api.pojo.ActivityDto;
import com.tarena.lbs.attach.api.AttachApi;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.BasePageQuery;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.common.principle.UserPrinciple;
import com.tarena.lbs.common.utils.AuthenticationContextUtils;
import com.tarena.lbs.content.dao.repository.ActionESRepository;
import com.tarena.lbs.content.dao.repository.ActionRepository;
import com.tarena.lbs.content.dao.repository.ArticleESRepository;
import com.tarena.lbs.content.dao.repository.ArticleRepository;
import com.tarena.lbs.content.feign.UserClient;
import com.tarena.lbs.content.pojo.param.ArticleActionParam;
import com.tarena.lbs.content.pojo.param.ArticleContentParam;
import com.tarena.lbs.content.pojo.po.ActionSearch;
import com.tarena.lbs.content.pojo.po.ArticleSearch;
import com.tarena.lbs.content.pojo.query.ArticleQuery;
import com.tarena.lbs.content.pojo.vo.ArticleActionPageResultVO;
import com.tarena.lbs.content.pojo.vo.ArticleActionVO;
import com.tarena.lbs.content.pojo.vo.ArticleVO;
import com.tarena.lbs.content.pojo.vo.UserVO;
import com.tarena.lbs.content.service.ArticleService;
import com.tarena.lbs.content.utils.PageResultBuilder;
import com.tarena.lbs.content.utils.SequenceGenerator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class ArticleServiceImpl implements ArticleService {
    private final ArticleESRepository articleESRepository;
    private final ActionESRepository actionESRepository;
    private final ArticleRepository articleRepository;
    private final ActionRepository actionRepository;
    private final UserClient userClient;
    @DubboReference
    private ActivityApi activityApi;
    @DubboReference
    private AttachApi attachApi;
    @Override
    public PageResult<ArticleVO> articleList(ArticleQuery query){
        Pageable pageable = PageRequest.of(query.getPageNo()-1, query.getPageSize());
        Page<ArticleSearch> page = articleESRepository.findAll(pageable);
        List<ArticleVO> result = page.map(articleSearch -> {
            ArticleVO articleVO = new ArticleVO();
            BeanUtils.copyProperties(articleSearch,articleVO);
            return articleVO;
        }).stream().toList();
        return PageResultBuilder.build(result);
    }
    @Override
    public void addArticle(ArticleContentParam param) {
        ArticleSearch articleSearch = new ArticleSearch();
        BeanUtils.copyProperties(param,articleSearch);
        if (articleSearch.getId() != null && articleSearch.getId() != 0) {
            articleSearch.setCreateTime(new Date());
            articleSearch.setUpdateTime(new Date());
        }else {
            articleSearch.setId(SequenceGenerator.sequence());
            articleSearch.setUpdateTime(new Date());
        }
        log.debug("添加文章:{}",articleSearch);
        articleESRepository.save(articleSearch);
    }
    @Override
    public Set<String> articleLabels(ArticleQuery articleQuery) {
        Pageable pageable = PageRequest.of(articleQuery.getPageNo()-1, articleQuery.getPageSize());
        Page<ArticleSearch> page = articleESRepository.findAll(pageable);
        return page.map(ArticleSearch::getArticleLabel).stream().collect(Collectors.toSet());
    }
    @Override
    public ArticleVO articleDetail(Integer id){
        ArticleVO articleVO = new ArticleVO();
        articleESRepository.findById(id).ifPresent(
                es -> {
                    UserPrinciple user = AuthenticationContextUtils.get();
                    Map<String,Integer> counts = articleRepository.getAllFieldsFromArticle(id);
                    counts.put("accessCount",counts.getOrDefault("accessCount",0)+1);
                    BeanUtils.copyProperties(es,articleVO);
                    articleVO.setAccessCount(counts.getOrDefault("accessCount",0));
                    if (es.getActivityId()!=null) {
                        try {
                            if (activityApi.activityVisible(user.getId(), es.getActivityId())) {
                                ActivityDto activity = activityApi.getActivityById(es.getActivityId());
                                articleVO.setActivityWord(activity.getDescribes());
                            } else articleVO.setActivityId(null);
                        } catch (BusinessException e) {
                            throw new RuntimeException(e);
                        }
                    } else log.info("文章不存在活动");
                }
        );
        log.debug("查看文章详情:{}",articleVO);
        return articleVO;
    }
    @Override
    public void saveBehavior(ArticleActionParam param) {
        UserPrinciple user = AuthenticationContextUtils.get();
        updateArticle(param);
        updateUser(param,user.getId());
        ActionSearch actionSearch = new ActionSearch();
        BeanUtils.copyProperties(param,actionSearch);
        ArticleVO targetArticle = articleDetail(param.getId());
        actionSearch.setArticleTitle(targetArticle.getArticleTitle());
        actionSearch.setArticleLabel(targetArticle.getArticleLabel());
        actionSearch.setArticleType(targetArticle.getArticleCategory());
        actionSearch.setArticleUserId(targetArticle.getUserId());
        actionSearch.setBehaviorUserId(user.getId());
        actionSearch.setCreateTime(new Date());
        actionESRepository.save(actionSearch);
    }
    @Override
    public ArticleActionPageResultVO behaviorLists(ArticleQuery query) {
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userVO,userClient.detail().getData());
        BasePageQuery basePageQuery = new BasePageQuery();
        Pageable pageable = PageRequest.of(basePageQuery.getPageNo()-1, basePageQuery.getPageSize());
        Page<ArticleSearch> articlePage = articleESRepository.findAll(pageable);
        Page<ActionSearch> actionPage = actionESRepository.findAll(pageable);
        List<ActionSearch> userActions = actionPage.stream().filter(
                actionSearch -> actionSearch.getBehaviorUserId().equals(userVO.getId()))
                .toList();
        List<ActionSearch> userFutureLikeActions = userActions.stream().filter(
                actionSearch -> actionSearch.getBehavior().equals(1))
                .toList();
        List<ActionSearch> userFutureCollectActions = userActions.stream().filter(
                actionSearch -> actionSearch.getBehavior().equals(2))
                .toList();
        List<ActionSearch> userFutureCommentActions = userActions.stream().filter(
                actionSearch -> actionSearch.getBehavior().equals(3))
                .toList();
        PageResult<ArticleActionVO> likeFuturePageResult = PageResultBuilder.build(
                getArticleAction(userFutureLikeActions, articlePage, userVO));
        log.debug("用户点赞列表：{}",userFutureLikeActions);
        PageResult<ArticleActionVO> collectFuturePageResult = PageResultBuilder.build(
                getArticleAction(userFutureCollectActions, articlePage, userVO));
        log.debug("用户收藏列表：{}",userFutureCollectActions);
        PageResult<ArticleActionVO> commentFuturePageResult = PageResultBuilder.build(
                getArticleAction(userFutureCommentActions, articlePage, userVO));
        log.debug("用户评论列表：{}",userFutureCommentActions);
        return new ArticleActionPageResultVO(likeFuturePageResult,collectFuturePageResult,commentFuturePageResult);
    }
    @Override
    public void updateArticle(ArticleActionParam param) {
        Map<String,Integer> counts = articleRepository.getAllFieldsFromArticle(param.getId());
        switch (param.getBehavior()){
            case 1 -> {
                counts.put("likeCount",counts.getOrDefault("likeCount",0)+1);
            }
            case 2 -> {
                counts.put("favoriteCount",counts.getOrDefault("favoriteCount",0)+1);
            }
        }
        articleRepository.saveAllFieldsToArticle(param.getId(),counts);
    }
    @Override
    public List<ArticleActionVO> getArticleAction(List<ActionSearch> actions,Page<ArticleSearch> articles,UserVO user){
        return actions.stream().map(actionSearch -> {
                    ArticleActionVO articleActionVO = new ArticleActionVO();
                    BeanUtils.copyProperties(actionSearch,articleActionVO);
                    articles.forEach(articleSearch -> {
                        if (articleSearch.getId().equals(actionSearch.getArticleId())){
                            articleActionVO.setArticleCover(articleSearch.getArticleCover());
                        }
                    });
                    articleActionVO.setLikePersonImg(user.getUserNickPicture());
                    return articleActionVO;
                }).toList();
    }
    public void updateUser(ArticleActionParam param,Integer userId){
        Map<String,Integer> counts = actionRepository.getAllFieldsFromArticle(userId);
        switch (param.getBehavior()){
            case 1 -> {
                counts.put("likeCount",counts.getOrDefault("likeCount",0)+1);
            }
            case 2 -> {
                counts.put("favoriteCount",counts.getOrDefault("favoriteCount",0)+1);
            }
            case 3 -> {
                counts.put("commentCount",counts.getOrDefault("commentCount",0)+1);
            }
        }
        actionRepository.saveAllFieldsToArticle(userId,counts);
    }
}
